﻿using System;

namespace Teal.Compiler {

    /// <summary>
    /// 表示一个编译器。用于存储相关的配置数据以及提供公共的编译辅助函数。
    /// </summary>
    public static partial class Compiler {

        /// <summary>
        /// 当前程序的入口函数。
        /// </summary>
        /// <param name="args">启动参数数组。</param>
        public static int Main(string[] args) {
            if (Compiler.parseArgs(args)) {
                Compiler.run();
                //try {
                //    Compiler.run();
                //} catch (Exception e) {
                //    Compiler.error(ErrorCode.none, String.Format("编译器内部错误：“{0}”", e.Message));
                //}
                if (!Compiler.hideResult) {
                    if (Compiler.errorCount > 0) {
                        Console.WriteLine("编译失败：{0} 个错误，{1} 个警告", errorCount, warningCount);
                    } else if (warningCount > 0) {
                        Console.WriteLine("编译成功 - {0} 个警告: {1}", Compiler.warningCount, Compiler.options.outputPath);
                    } else {
                        Console.WriteLine("编译成功: {0}", Compiler.warningCount, Compiler.options.outputPath);
                    }
                }
                if (Compiler.runIfSuccess && Compiler.errorCount == 0) {
                    try {
                        System.Diagnostics.Process.Start(Compiler.options.outputPath);
                    } catch (Exception e) {
                        Compiler.error(ErrorCode.none, String.Format("无法执行生成文件：“{0}”", e.Message));
                    }
                }
            }
            return Compiler.errorCount;
        }

        private const string Version = "1.0.0";

        private const string Logo = "Teal 编译器 " + Version + " 。保留所有版权";

        private const string BasicUsage = Logo + @"

用法：
    tc <源文件名> -out:<输出文件名>";

        private const string Usage = BasicUsage + @"
 
选项：
    -out                  指定输出的文件名
    -help                 打印本帮助信息
    -logo                 打印编译器版权
    -version              打印编译器版本
    -showResult           是否在编译结束后报告相关信息
    -run                  是否在编译成功后执行程序
";

        /// <summary>
        /// 获取或设置是否在编译结束后报告相关信息。
        /// </summary>
        public static bool hideResult;

        /// <summary>
        /// 指示是否在编译成功后执行程序。
        /// </summary>
        public static bool runIfSuccess ;

        /// <summary>
        /// 尝试解析所有命令行参数。
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private static bool parseArgs(string[] args) {

            // 空参数直接显示 logo
            if (args.Length == 0) {
                Console.Write(BasicUsage);
                return false;
            }

            foreach (string arg in args) {

                // 解析为路径。
                string key, value;
                if (!tryParseCommandArg(arg, out key, out value)) {
                    addSource(arg);
                    continue;
                }

                // 解析为编译器命令
                switch (key) {
                    case "?":
                    case "help":
                        Console.Write(Usage);
                        return false;

                    case "logo":
                        Console.Write(Logo);
                        return false;

                    case "version":
                        Console.Write(Version);
                        return false;

                    case "showresult":
                        hideResult = value == "false";
                        continue;

                    case "run":
                        runIfSuccess = value == "false";
                        continue;

                }

                // 解析为编译配置。
                applyOption(key, value);

            }

            return true;

        }

        /// <summary>
        /// 尝试解析指定命令行参数字符串。
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private static bool tryParseCommandArg(string arg, out string key, out string value) {
            if (string.IsNullOrEmpty(arg) || arg[0] != '-') {
                key = null;
                value = null;
                return false;
            }

            int colon = arg.IndexOf(':');
            if (colon >= 0) {
                key = arg.Substring(1, colon - 1).TrimEnd();
                value = arg.Substring(colon + 1).TrimStart();
            } else {
                key = arg.Substring(1);
                value = null;
            }

            key = key.ToLowerInvariant();
            return true;
        }

    }

}